/*
 * NetworkContext.cpp
 *
 *  Created on: Jul 13, 2008
 *      Author: Kyle
 */

#include "NetworkManager.h"


__gnu_cxx::hash_map<int, AdapterListener*>* NetworkManager::active_listeners = new __gnu_cxx::hash_map<int, AdapterListener*>();
__gnu_cxx::hash_map<int, pcap_t*>* NetworkManager::adapter_table = new __gnu_cxx::hash_map<int, pcap_t*>();

NetworkManager::NetworkManager() {
}

NetworkManager::~NetworkManager() {
	//delete adapter;
}


pcap_t *NetworkManager::getAdapter(int id) {
	return adapter_table->find(id)->second;
}

void NetworkManager::init() {
	// find the device
	pcap_if_t *alldevs;				// list of devices
	pcap_t* adapter;				// activated adapter
	char errbuf[PCAP_ERRBUF_SIZE];	// duh?
	u_int netmask;					// used for compiling filter
	bpf_program fcode;				// filter program
	int i = 0;						// ordered id of dev, used for key in adapter_list

	pcap_findalldevs(&alldevs, errbuf);
	for (pcap_if_t *d = alldevs; d != NULL; d = d->next) {
		printf("\n%d.\t%s\n\t%s", i+1, d->name, d->description);
		adapter = pcap_open_live(d->name	// name of the device
								,65536		// portion of the packet to capture
											// 65536 guarantees that the whole packet will be captured on all the link layers
								,false		// promiscuous mode
								,1000		// read timeout
								,errbuf);	// error buffer
		if (adapter) {
			adapter_table->insert(std::pair<int, pcap_t*>(i, adapter));

		    // compile filters (tcp/ip)
		    if (d->addresses) {
		    	//netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
		    } else {
		    	netmask = 0xfffff;
		    }


		    if (pcap_compile(adapter, &fcode, "ip and tcp", 1, netmask) < 0) {
		    	printf("Unable to compile the packet filter.\n");
		    	pcap_freealldevs(alldevs);
		    }

		    // enable filter
		    pcap_setfilter(adapter, &fcode);
		}
		i++;
	}



	// done init, dump the devs
    pcap_freealldevs(alldevs);

}
AdapterListener* NetworkManager::activate(int id) {

	return NetworkManager::activate(id, false);

}


AdapterListener* NetworkManager::activate(int id, bool isPromisuous) {
	printf("\nactivating adapter %d", id);
	char errbuf[PCAP_ERRBUF_SIZE];
	AdapterListener *listener;
	boost::thread *listen_thread;
	if (adapter_table->find(id) != adapter_table->end()) {
		printf("\nfound adapter %d", id);

		if (active_listeners->find(id) == active_listeners->end()) {
			printf("\nstarting new listener.");
			listener = new AdapterListener(adapter_table->find(id)->second);
			listener->run();
			active_listeners->insert(std::pair<int, AdapterListener*>(id,listener));
		} else {
			printf("\nadapter is already being monitored.");
			listener = active_listeners->find(id)->second;
		}
	}
	return listener;


}


